// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the GNU General Public License v3

// Common.h
//

#pragma once

#include <sstream>
class Color;

COLORREF convertColor(const Color& color);
Color convertColor(COLORREF color);


template<class T> 
void dbg(const T & t) 
{
    std::ostringstream oss;
    oss << t << "\n";
    ::OutputDebugStringA(oss.str().c_str());
}

template<class T1, class T2> 
void dbg(const T1 & t1, const T2 & t2) 
{
    std::ostringstream oss;
    oss << t1 << " " << t2 << "\n";
    ::OutputDebugStringA(oss.str().c_str());
}

template<class T1, class T2, class T3> 
void dbg(const T1 & t1, const T2 & t2, const T3 & t3) 
{
    std::ostringstream oss;
    oss << t1 << " " << t2 << " " << t3 << "\n";
    ::OutputDebugStringA(oss.str().c_str());
}

template<class T1, class T2, class T3, class T4> 
void dbg(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4) 
{
    std::ostringstream oss;
    oss << t1 << " " << t2 << " " << t3 << " " << t4 << "\n";
    ::OutputDebugStringA(oss.str().c_str());
}


// TODO these should be in their own header file
#include <cmath>
// meters per microsecond (e.g., 2/1M means 1m/s)
const double SECS_IN_US = 1 / (1000. * 1000.);
const double STEPPING_SPEED = 8 * SECS_IN_US;
const double EPSILON = 1e-8;
const double PI = 3.14159265358979323846264338327;
const double TWO_PI = 2 * PI;
const double HALF_PI = .5 * PI;
const double SQRT_TWO = std::sqrt(2.);
const double SQRT_THREE = std::sqrt(3.);

inline double degToRad(double deg)
{
    return deg * PI / 180.;
}

inline double radToDeg(double rad)
{
    return rad / PI * 180.;
}


// Serialization helpers
// TODO these should so be somewhere else
void writeTextToArchive(const std::string & str, CArchive & ar);
std::string readCompleteTextArchive(CArchive & ar);


template<class T> 
void copy_array(T dest[], T const src[], int n) 
{
    for(int i = 0; i < n; ++i)
        dest[i] = src[i];
}

template<class T> 
void set_array(T dest[], T const & x0) 
{
    dest[0] = x0;
}

template<class T, class X> 
void set_array(T & dest, X const &x0, X const &x1) 
{
    dest[0] = x0;   dest[1] = x1;
}

template<class T> 
void set_array(T dest[], T const &x0, T const &x1, T const &x2) 
{
    dest[0] = x0;   dest[1] = x1;   dest[2] = x2;
}

template<class T> 
void set_array(T dest[], T const &x0, T const &x1, T const &x2, T const &x3) 
{
    dest[0] = x0;   dest[1] = x1;   dest[2] = x2;   dest[3] = x3;
}


inline void error(const char* msg)
{
	dbg(msg);
	throw std::runtime_error(msg);
}

template<class T>
void error(const T& t)
{
	std::ostringstream oss;
	oss << t;
	error(oss.str().c_str());
}

template<class T0, class T1>
void error(const T0& t0, const T1& t1)
{
	std::ostringstream oss;
	oss << t0 << t1;
	error(oss.str().c_str());
}
